#pragma once

#include "ip_addr.hh"
#include <span>
#include <utility>

namespace wb
{
namespace net
{
struct socket_option
{
    enum class proto
    {
        tcp,
        udp
    };

    enum class iotype
    {
        bio,
        nbio
    };

    domain_t d;
    proto p;
    iotype b;
};

class socket
{
  public:
    socket() = default;
    explicit socket(int fd) : fd_{fd}
    {
    }
    socket(const socket&) = delete;
    socket(socket&& other) : fd_{std::exchange(other.fd_, -1)}
    {
    }
    socket& operator=(const socket&) = delete;
    socket& operator=(socket&& other) noexcept;
    ~socket();

  public:
    static int proto(socket_option::proto proto);
    bool set_iotype(socket_option::iotype t);
    void close_socket();
    bool is_valid() const
    {
        return fd_ != -1;
    }
    int native_handle() const
    {
        return fd_;
    }

  private:
    int fd_{-1};
};

socket create_socket_for_connect(const socket_option& opts);

socket create_socket_for_listen(const socket_option& opts,
                                const ip_address& addr,
                                uint16_t port,
                                int32_t backlog = 128);

}  // namespace net
}  // namespace wb
